package com.xy.mvvmdemo.view

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import com.xy.mvvmdemo.R

/**
 * @ClassName FlowLayout
 * @Author xy
 * @Date 2021/7/9 16:18
 * @Description 流布局
 */
class FlowLayout : ViewGroup {
    //度量子view的大小
    var mHorizontalSpacing = 20 //子控件之间的水平间距
    var mVerticalSpacing = 20//子控件之间的垂直间距

    var allLines = mutableListOf<MutableList<View>>()//记录所有的行，一行一行的存储，用于layout
    var lineHeights = mutableListOf<Int>()//记录每一行的行高，用于1ayout

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ){
        val typedArray = context?.obtainStyledAttributes(attrs, R.styleable.ActionBar) //获取自定义属性
        val title = typedArray?.getString(R.styleable.ActionBar_subtitle)
    }

    private fun initMeasureParams() {
        allLines = mutableListOf()
        lineHeights = mutableListOf()
    }



    //度量
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        initMeasureParams()
        var lineViews = mutableListOf<View>()//保存一行中所有的view
        var lineWidthUsed = 0 //记录这行已经使用了多宽的size
        var lineHeight = 0 //一行的行高

        var parentNeededWidth = 0//measure过程中，子view要求的父ViewGroup的宽
        var parentNeededHeight = 0 //measure过程中，子view要求的父ViewGroup的高

        var selfWidth = MeasureSpec.getSize(widthMeasureSpec) //父容器的宽度
        var selfHeight = MeasureSpec.getSize(heightMeasureSpec) //父容器的高度


        for (i in 0 until childCount) {
            var childView = getChildAt(i)
            var childLP = childView.layoutParams
            var childWidthMeasureSpec = getChildMeasureSpec(//转化成具体的像素
                widthMeasureSpec,
                paddingLeft + paddingRight,
                childLP.width
            ) //获取子控件宽度大小

            var childHeightMeasureSpec = getChildMeasureSpec( //转化成具体的像素
                heightMeasureSpec,
                paddingTop + paddingBottom,
                childLP.height
            )//获取子控件高度大小
            childView.measure(childWidthMeasureSpec, childHeightMeasureSpec) //度量完之后才能获取子控件的具体值
            //获取子view的宽高
            var childMeasureWidth = childView.measuredWidth
            var childMeasureHeight = childView.measuredHeight

            //通过宽度来判断是否换行，通过换行后的每一行的行高来获取ViewGroup的行高
            if (childMeasureWidth + lineWidthUsed + mHorizontalSpacing >= selfWidth) { //判断是否需要换行
                //记录每一行的view 和高度
                allLines.add(lineViews)
                lineHeights.add(lineHeight)

                //一旦换行，我们就可以判断当前行需要的宽和高了，所以此时要记录下来
                parentNeededHeight += lineHeight + mVerticalSpacing;
                parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing)


                //重置
                lineViews = mutableListOf()
                lineWidthUsed = 0
                lineHeight = 0
            }

            //记录每一行有哪些view
            lineViews.add(childView)
            //每一行都有自己的宽高
            lineWidthUsed += childMeasureWidth + mHorizontalSpacing //需要添加一个空格  还没弄明白
            lineHeight = Math.max(lineHeight, childMeasureHeight)//行高最大值
        }

        if (lineViews.size>0){ //为了防止最后一行没有达到父控件的宽度
            allLines.add(lineViews)
            lineHeights.add(lineHeight)
            parentNeededHeight += lineHeight + mVerticalSpacing;
            parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing)
        }

        //度量自已大小
        //根据子View的度景结果，来重新度量自己ViewGroup
        //作为一个ViewGroup，它自己也是一个View.它的大小也需要根据它的父亲给它提供的宽高来度量
        var widthMode = MeasureSpec.getMode(widthMeasureSpec)
        var heightMode = MeasureSpec.getMode(heightMeasureSpec)
        var realWidth = if (widthMode == MeasureSpec.EXACTLY) {//判断父容器是否有确切的值
            selfWidth
        } else {
            parentNeededWidth
        }
        var realHeight = if (heightMode == MeasureSpec.EXACTLY) {//判断父容器是否有确切的值
            selfHeight
        } else {
            parentNeededHeight
        }
        setMeasuredDimension(realWidth, realHeight) //度量父容器


    }

    //布局
    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var  lineCount = allLines.size
        var curL = paddingLeft
        var curT = paddingTop
        for (i in 0 until lineCount){
            var lineViews = allLines[i]
            var lineheight = lineHeights[i]
            for (j in 0 until lineViews.size){
                var view = lineViews[j]
                var left = curL//父容器的左内间距
                var top = curT//父容器的右内间距
                var right = left + view.measuredWidth
                var bottom = top + view.measuredHeight
                view.layout(left,top,right,bottom) //布局子view
                curL = right + mHorizontalSpacing
            }
            curL = paddingLeft
            curT = paddingTop + lineheight + mVerticalSpacing
        }

    }
}